package github.fafaovo.common.guiblock.tileentity;

import com.mojang.datafixers.DSL;
import github.fafaovo.common.config.exampleconfig;
import github.fafaovo.common.guiblock.MyIntArray;
import github.fafaovo.common.guiblock.block.ExampleInitialMachine;
import github.fafaovo.common.guiblock.containers.ExampleBurnMachineContainers;
import github.fafaovo.common.guiblock.containers.ExampleInitialContainers;
import github.fafaovo.common.mycapability.ISpeedUpCapability;
import github.fafaovo.common.world.ExampleWorldSaveData;
import github.fafaovo.core.init.ItemInit;
import github.fafaovo.core.registry.CommonSetupEventHandler;
import github.fafaovo.deepcapacity;
import github.fafaovo.network.NetworkRegistryHandler;
import github.fafaovo.network.Packet.Power;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.player.PlayerInventory;
import net.minecraft.entity.player.ServerPlayerEntity;
import net.minecraft.inventory.container.Container;
import net.minecraft.inventory.container.INamedContainerProvider;
import net.minecraft.item.Item;
import net.minecraft.item.Items;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.potion.EffectInstance;
import net.minecraft.potion.Effects;
import net.minecraft.tileentity.ITickableTileEntity;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityType;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TranslationTextComponent;
import net.minecraft.world.server.ServerWorld;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.energy.CapabilityEnergy;
import net.minecraftforge.energy.IEnergyStorage;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.network.PacketDistributor;
import net.minecraftforge.items.CapabilityItemHandler;
import net.minecraftforge.items.IItemHandler;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.registries.ObjectHolder;
import org.antlr.v4.runtime.misc.NotNull;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;

@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public class ExampleInitialEntity extends TileEntity implements ITickableTileEntity, INamedContainerProvider {

    private int energy = 0;
    private final int MaxEnergy = 192_000;
    public static final String NAME = "deepcapacity:initial_machine";

    //同步数据的数组
    private MyIntArray itemNumber = new MyIntArray();

    private final ItemStackHandler UP = new ItemStackHandler(1)
    {
        @Override
        protected void onContentsChanged(int slot) {
            ExampleInitialEntity.this.markDirty(); //保存数据
        }
    };

    @ObjectHolder(NAME)
    public static TileEntityType<ExampleInitialEntity> TILE_ENTITY_TYPE;

    //机器实体注册
    @SubscribeEvent
    public static void onRegisterTileEntityType(@Nonnull RegistryEvent.Register<TileEntityType<?>> event)
    {
        //todo
        event.getRegistry().register(TileEntityType.Builder.create(
                ExampleInitialEntity::new,
                        ExampleInitialMachine.BLOCK)
                .build(DSL.remainderType()).setRegistryName(NAME));
    }

    public ExampleInitialEntity() {
        super(TILE_ENTITY_TYPE);
    }

    @Override
    public void read(@NotNull BlockState state, CompoundNBT compound) {
        this.energy = compound.getInt("InitialEnergy");
        super.read(state, compound);
    }
    @Nonnull
    @Override
    public CompoundNBT write(@Nonnull CompoundNBT compound)
    {
        compound.putInt("InitialEnergy", this.energy);
        return super.write(compound);
    }

    int count = 0;
    int amount = exampleconfig.example_integer.get() * 2;
    int scope = exampleconfig.machine_pos.get();
    boolean exb = exampleconfig.example_boolean.get();
    @Override
    public void tick() {
        if (!world.isRemote) {

            this.itemNumber.set(0, this.UP.getStackInSlot(0).getCount());
            this.itemNumber.set(1, itemNumber.ratio(64,MaxEnergy,energy));
            //this.itemNumber.set(2, itemNumber.ratio(14,brun,brunTime *5));
            this.itemNumber.set(3,this.energy);
            this.markDirty();
        }
        if (this.world != null && !this.world.isRemote)
        {
            count++;
            if(count == 100)
            {
                count = 0;
                TileEntity tileEntity = getTileEntity();
                if(tileEntity instanceof ExampleInitialEntity)
                {
                    //获取这个区域的玩家列表
                    AxisAlignedBB axisalignedbb = (new AxisAlignedBB(this.pos)).grow(scope).expand(0, (double)this.world.getHeight(), 0);
                    List<PlayerEntity> list = this.world.getEntitiesWithinAABB(PlayerEntity.class, axisalignedbb);

                    for(PlayerEntity playerentity : list) {
                        int diff = Math.min(this.energy, 1000);
                        if (diff > 0)
                        {
                            this.energy -= diff;
                            this.markDirty();
                            //playerentity.addPotionEffect(new EffectInstance(Effects.JUMP_BOOST,100,5, true, true));
                            LazyOptional<ISpeedUpCapability> capability = playerentity.getCapability(CommonSetupEventHandler.SPEED_UP_CAPABILITY);
                            capability.ifPresent((c)->{
                                float examplePower = c.getLevel();
                                Item item = ItemInit.CAP_FOOD.get();
                                if(item.equals(this.UP.extractItem(0, 1, true).getItem()))
                                {
                                    ServerWorld serverWorld = playerentity.getCommandSource().getWorld();
                                    if(ExampleWorldSaveData.get(serverWorld).getPower() > 0)
                                    {
                                        this.UP.extractItem(0,1,false);
                                        if(!exb)
                                        {

                                            int power = ExampleWorldSaveData.get(serverWorld).getPower() + 1;
                                            power = Math.min(power, 100);
                                            ExampleWorldSaveData.get(serverWorld).setPower(power);
                                        }
                                        else
                                        {
                                            int power = ExampleWorldSaveData.get(serverWorld).getPower() - 1;
                                            power = Math.max(power, 0);
                                            ExampleWorldSaveData.get(serverWorld).setPower(power);
                                        }
                                    }

                                }

                                if(!exb)
                                {
                                    int maxPower = exampleconfig.max_power.get();
                                    if(examplePower + amount < maxPower)
                                        c.setLevel(examplePower + amount);
                                    else
                                        c.setLevel(maxPower);
                                }
                                else
                                {
                                    if(examplePower - amount <= 0)
                                        c.setLevel(0);
                                    else
                                        c.setLevel(examplePower - amount);
                                }
                                NetworkRegistryHandler.CHANNEL.send(
                                        PacketDistributor.PLAYER.with(
                                                ()->(ServerPlayerEntity) playerentity),//为了区分不同的玩家
                                        new Power(c.getLevel())
                                );
                            });
                        }
                    }

                }
            }
        }
    }



    private final LazyOptional<IEnergyStorage> lazyOptional  = LazyOptional.of(() -> new IEnergyStorage()
    {
        @Override //接收能量
        public int receiveEnergy(int maxReceive, boolean simulate)
        {
            int energy = this.getEnergyStored(); //当前能量
            int diff = Math.min(this.getMaxEnergyStored() - energy, maxReceive); //能接收多少能量
            if (!simulate)
            {
                ExampleInitialEntity.this.energy += diff;
                if (diff != 0)
                {
                    ExampleInitialEntity.this.markDirty(); //保存
                }
            }
            return diff;
        }

        @Override
        public int extractEnergy(int maxExtract, boolean simulate)
        {
            return 0;
        }

        @Override
        public int getEnergyStored()
        {
            return Math.max(0, Math.min(this.getMaxEnergyStored(), ExampleInitialEntity.this.energy));
        }

        @Override
        public int getMaxEnergyStored()
        {
            return MaxEnergy;
        }

        @Override
        public boolean canExtract()
        {
            return false;
        }

        @Override
        public boolean canReceive()
        {
            return true;
        }
    });




    //界面名
    @Override
    public ITextComponent getDisplayName() {
        return new TranslationTextComponent("gui." + deepcapacity.MOD_ID + ".initial_machine");
    }

    //创建界面
    @Nullable
    @Override
    public Container createMenu(int sycID, PlayerInventory inventory, PlayerEntity player) {
        //todo
        return new ExampleInitialContainers(sycID, inventory, this.pos, this.world, itemNumber);
    }

    //让实体具备交互的功能
    @Nonnull
    @Override
    public <T> LazyOptional<T> getCapability(@Nonnull Capability<T> cap, @Nullable Direction side) {
        //和forge的物品进行对比
        Capability<IItemHandler> itemHandlerCapability = CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
        if(cap.equals(itemHandlerCapability))
        {
            //方块的方向和交互口的方向是否一致
            if(Direction.UP.equals(side))
            {
                return LazyOptional.of(()->this.UP).cast();
            }
        }
        boolean isEnergy = Objects.equals(cap, CapabilityEnergy.ENERGY) && side.getAxis().isHorizontal();
        if(isEnergy)
        {
            return this.lazyOptional.cast();
        }
        return super.getCapability(cap, side);
    }

}
